#!/usr/bin/python3
#-*-coding:utf-8-*-

###############################################################
## Name       : gen_agent
## Author     : gaojiaming
## Date       : Fri Aug 26 10:30:00 CST 2022
## Description:
##
##
###############################################################

import sys
import os
import re
import argparse

class Signal:#{{{
    def __init__(self, name, width, rand):
        self.name   = name
        self.width  = width
        self.rand   = rand

    def __str__(self):
        str = "Class Signal\n"
        str = str + "    name   : %s\n" % self.name
        str = str + "    width  : %s\n" % self.width
        str = str + "    rand   : %s\n" % self.rand
        return str

    def gen_inf_point0(self):
        str = "    logic [{0} -1:0] {1};\n".format(self.width, self.name)
        return str
    def gen_inf_point1(self):
        str = "        output {0};\n".format(self.name)
        return str
    def gen_inf_point2(self):
        str = "        input {0};\n".format(self.name)
        return str

    def gen_trc_point0(self):
        if self.rand == "Y":
            str = "    rand bit [{0} -1:0] {1};\n".format(self.width, self.name)
        else:
            str = "         bit [{0} -1:0] {1};\n".format(self.width, self.name)
        return str
    def gen_trc_point1(self):
        str = "        `uvm_field_int({0}, UVM_ALL_ON)\n".format(self.name)
        return str
    def gen_trc_point2(self):
        str = "    extern constraint {0}_cons;\n".format(self.name)
        return str
    def gen_trc_point3(self, agent_name):
        str = "constraint {0}_transaction::{1}_cons{{\n".format(agent_name, self.name)
        str+= "}\n"
        return str
    def gen_trc_point4(self):
        str = "    to.{0} = this.{0};\n".format(self.name)
        return str    

    def gen_drv_point0(self):
        str = "        this.vif.drv.{0} <= pkt.{0};\n".format(self.name)
        return str
    def gen_drv_point1(self):
        str = "    this.vif.drv.{0} <= 'dx;\n".format(self.name)
        return str
    def gen_drv_point2(self):
        str = "            this.vif.drv.{0} <= 'dx;\n".format(self.name)
        return str

    def gen_mon_point0(self):
        str = "            data.{0} = this.vif.mon.{0};\n".format(self.name)
        return str


pass#}}}

def input_cfg_file():#{{{
    if len(sys.argv) <= 1:
        print("ERROR: You need input a agent name")
        sys.exit()
    agent_name = sys.argv[1]
    agent_cfg_file = agent_name + ".cfg"
    if not os.path.exists(agent_cfg_file):
        os.system("cp {0}/agent_cfg ./{1}".format(root_path, agent_cfg_file))
        os.system("gvim ./{}".format(agent_cfg_file))
        rsp=input("Please input y after complete: ")
        if rsp != "y":
            print("ERROR: You need input a agent cfg_file")
            sys.exit()
    agent_path = agent_name + "_utils"
    return agent_name, agent_cfg_file, agent_path
#}}}
    
def sys_cfg_file(cfg_file):#{{{
    sig_list = []
    with open(cfg_file, "r") as hd:
        handle = hd.readlines()
        for line in handle:
            arr = line.split()
            if arr[0] == "SIGNAL":
                continue
            sig = Signal(arr[0], arr[1], arr[2])
            sig_list.append(sig)
            #print(sig)
    return sig_list
#}}}

def mkdir_path(agent_path):#{{{
    utils_path = work_path
    if re.search(r"/{0}$".format(agent_path), work_path):
        utils_path = work_path
        os.system("mkdir -p src")
        os.system("mkdir -p test")
    else:
        os.system("mkdir -p {}".format(agent_path))
        utils_path = work_path + "/" + agent_path
        os.system("cd {}; mkdir -p src".format(agent_path))
        os.system("cd {}; mkdir -p test".format(agent_path))
    return utils_path
#}}}

def copy_src(utils_path, agent_name):#{{{
    src_path  = utils_path + "/src"
    test_path = utils_path + "/test"
    os.system("cp {0}/gjm_utils/*.lst {1}/ -rf".format(root_path, utils_path))
    os.system("cp {0}/gjm_utils/src/* {1}/ -rf".format(root_path, src_path))
    os.system("cp {0}/gjm_utils/test/* {1}/ -rf".format(root_path, test_path))

    os.system("mv {0}/gjm_agent.sv {0}/{1}_agent.sv".format(src_path, agent_name))
    os.system("mv {0}/gjm_transaction.sv {0}/{1}_transaction.sv".format(src_path, agent_name))
    os.system("mv {0}/gjm_driver.sv {0}/{1}_driver.sv".format(src_path, agent_name))
    os.system("mv {0}/gjm_ready_drv.sv {0}/{1}_ready_drv.sv".format(src_path, agent_name))
    os.system("mv {0}/gjm_monitor.sv {0}/{1}_monitor.sv".format(src_path, agent_name))
    os.system("mv {0}/gjm_interface.sv {0}/{1}_interface.sv".format(src_path, agent_name))
    os.system("mv {0}/gjm_scb.sv {0}/{1}_scb.sv".format(src_path, agent_name))
    os.system("mv {0}/gjm_sequence.sv {0}/{1}_sequence.sv".format(src_path, agent_name))
    os.system("mv {0}/gjm_sequencer.sv {0}/{1}_sequencer.sv".format(src_path, agent_name))
    os.system("mv {0}/gjm_env.sv {0}/{1}_env.sv".format(test_path, agent_name))
    os.system("mv {0}/gjm_sim.lst {0}/{1}_sim.lst".format(test_path, agent_name))
    os.system("mv {0}/gjm_utils.lst {0}/{1}_utils.lst".format(utils_path, agent_name))
    
    os.system("cd {0}; sed -i 's/gjm_/{1}_/g' *".format(src_path, agent_name))
    os.system("cd {0}; sed -i 's/GJM_/{1}_/g' *".format(src_path, agent_name.upper()))    
    os.system("cd {0}; sed -i 's/gjm_/{1}_/g' *".format(test_path, agent_name))
    os.system("cd {0}; sed -i 's/GJM_/{1}_/g' *".format(test_path, agent_name.upper()))
    os.system("cd {0}; sed -i 's/gjm_/{1}_/g' *.lst".format(utils_path, agent_name))

    tmp_list = []
    with open("{0}/{1}_utils.lst".format(utils_path, agent_name), "r") as hd:
        handle = hd.readlines()
        for line in handle:
            line = re.sub(r"PATH", utils_path, line)
            tmp_list.append(line)
    with open("{0}/{1}_utils.lst".format(utils_path, agent_name), "w") as hd:
        for line in tmp_list:
            hd.write(line)
    
    tmp_list = []
    with open("{0}/test/{1}_sim.lst".format(utils_path, agent_name), "r") as hd:
        handle = hd.readlines()
        for line in handle:
            line = re.sub(r"PATH", utils_path, line)
            tmp_list.append(line)
    with open("{0}/test/{1}_sim.lst".format(utils_path, agent_name), "w") as hd:
        for line in tmp_list:
            hd.write(line)
    
    return src_path, test_path
#}}}

def modify_file(agent_name, src_path, test_path, sig_list):#{{{
    tmp_list = []    
    agt_file = src_path + "/{0}_interface.sv".format(agent_name)
    with open(agt_file, "r") as hd:
        handle = hd.readlines()
        for line in handle:
            res0 = re.search(r"GEN_AGENT POINT0", line)
            res1 = re.search(r"GEN_AGENT POINT1", line)
            res2 = re.search(r"GEN_AGENT POINT2", line)
            if res0:
                for sig in sig_list:
                    tmp_list.append(sig.gen_inf_point0())
            elif res1:
                for sig in sig_list:
                    tmp_list.append(sig.gen_inf_point1())
            elif res2:
                for sig in sig_list:
                    tmp_list.append(sig.gen_inf_point2())                    
            else:
                tmp_list.append(line)
    with open(agt_file, "w") as hd:
        for line in tmp_list:
            hd.write(line)
    
    tmp_list = []
    agt_file = src_path + "/{0}_transaction.sv".format(agent_name)
    with open(agt_file, "r") as hd:
        handle = hd.readlines()
        for line in handle:
            res0 = re.search(r"GEN_AGENT POINT0", line)
            res1 = re.search(r"GEN_AGENT POINT1", line)
            res2 = re.search(r"GEN_AGENT POINT2", line)
            res3 = re.search(r"GEN_AGENT POINT3", line)
            res4 = re.search(r"GEN_AGENT POINT4", line)
            if res0:
                for sig in sig_list:
                    tmp_list.append(sig.gen_trc_point0())
            elif res1:
                for sig in sig_list:
                    tmp_list.append(sig.gen_trc_point1())
            elif res2:
                for sig in sig_list:
                    tmp_list.append(sig.gen_trc_point2())                    
            elif res3:
                for sig in sig_list:
                    tmp_list.append(sig.gen_trc_point3(agent_name))
            elif res4:
                for sig in sig_list:
                    tmp_list.append(sig.gen_trc_point4())
            else:
                tmp_list.append(line)
    with open(agt_file, "w") as hd:
        for line in tmp_list:
            hd.write(line)
    
    tmp_list = []
    agt_file = src_path + "/{0}_driver.sv".format(agent_name)
    with open(agt_file, "r") as hd:
        handle = hd.readlines()
        for line in handle:
            res0 = re.search(r"GEN_AGENT POINT0", line)
            res1 = re.search(r"GEN_AGENT POINT1", line)
            res2 = re.search(r"GEN_AGENT POINT2", line)
            if res0:
                for sig in sig_list:
                    tmp_list.append(sig.gen_drv_point0())
            elif res1:
                for sig in sig_list:
                    tmp_list.append(sig.gen_drv_point1())
            elif res2:
                for sig in sig_list:
                    tmp_list.append(sig.gen_drv_point2())
            else:
                tmp_list.append(line)
    with open(agt_file, "w") as hd:
        for line in tmp_list:
            hd.write(line)

    tmp_list = []
    agt_file = src_path + "/{0}_monitor.sv".format(agent_name)
    with open(agt_file, "r") as hd:
        handle = hd.readlines()
        for line in handle:
            res0 = re.search(r"GEN_AGENT POINT0", line)
            if res0:
                for sig in sig_list:
                    tmp_list.append(sig.gen_mon_point0())
            else:
                tmp_list.append(line)
    with open(agt_file, "w") as hd:
        for line in tmp_list:
            hd.write(line)

    os.system("chmod a+x {0}/check_fail.pl".format(test_path))

        
#}}}

def main():
    (agent_name, agent_cfg_file, agent_path) = input_cfg_file()
    sig_list = sys_cfg_file(agent_cfg_file)
    utils_path = mkdir_path(agent_path)
    (src_path, test_path) = copy_src(utils_path,agent_name)
    modify_file(agent_name, src_path, test_path, sig_list)

if __name__ == "__main__":
    print("%s is working" % __file__)
    global root_path
    global work_path
    root_path = sys.path[0]
    work_path = os.path.abspath('.')
    main()
